/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ThreadBasedSimulator;

/**
 *
 * @author mahesh
 */
public class IOThread extends Thread{
    
    public IOThread()
    {
        
    }
    public IOThread( Clock clk )
    {
        m_clock = clk;
        m_nDeviceRegsiters  = new int[64];
        m_bDirtyBits        = new boolean[64];  // Stores whether the values have changed since the last read
        
        IO_FETCH = 0;
        IO_STORE = 1;
        
        m_sScreenData   = "";
        m_sIOBuffer     = "";
        
    }
    
    ///////////////////////////////////////////////////////////
    // Functions to set an get variables from the IO subsystem
    ///////////////////////////////////////////////////////////
    int Fetch()
    {
        synchronized( m_bDirtyBits )
        {
            m_bDirtyBits[ m_nDevId ] = false;
            return m_nDeviceRegsiters[ m_nDevId ] ;
        }
    }
    
    void Store( )
    {
        synchronized( m_bDirtyBits )
        {
            m_nDeviceRegsiters[ m_nDevId ] = m_nVal;
            m_bDirtyBits[ m_nDevId ] = true;
        }
    }
    
    void SetOperation( int nOP )
    {        
        {
            m_nOperation = nOP;
            SetExecutionFlag();
        }
    }
    
    void ResetExecutionFlag()
    {
        m_bToBeExecuted = false;
    }
    
    void SetExecutionFlag()
    {
        m_bToBeExecuted = true;
    }
    
    public String GetScreenData()
    {
        String retval;
        synchronized( m_sScreenData )
        {
            retval = m_sScreenData;

            // Since the Screen data variable only holds incremental updates to the screen, we have to clear it
            m_sScreenData = "";
        }
        return retval;
    }
    public void SetScreenData( String sData )
    {
        synchronized( m_sScreenData )
        {
            m_sScreenData = sData;
        }
    }
    
    public void StoreToIOBuffer( String sData )
    {
        m_sIOBuffer = sData;
        synchronized( m_sScreenData )
        {
            m_sScreenData = m_sScreenData + "\n" + sData;
        }
    }
    ///////////////////////////////////////////////////////////
    // The main thread for the IO
    ///////////////////////////////////////////////////////////
    @Override
    public void run() {
        
        while( true )
        {
            synchronized( m_clock )
            {
                try {
                    
                    m_clock.wait();
                } catch (InterruptedException ex) {
                    System.out.println( "Exception in MemoryThread.wait : "+ ex );
                }
            }
            
            // at this point we have the clock's permission to go on        
            if( m_bToBeExecuted == true )
            {
                System.err.println(" MemoryThread, operation = " + m_nOperation );
                switch( m_nOperation )
                {
                    case 0:
                        // This fetch returns a character
                        Fetch();
                        break;
                    case 1:
                        Store();
                        break;
                    
                        
                }
                
                ResetExecutionFlag();
            }
                
                
        }
    }
    
    ///////////////////////////////////////////////////////////
    // The Data members of the IO thread
    ///////////////////////////////////////////////////////////
    private int     [] m_nDeviceRegsiters;
    private boolean [] m_bDirtyBits;
    
    private Clock   m_clock;
    
    private int     m_nOperation;
    private boolean m_bToBeExecuted;
    
    private int     m_nDevId;
    private int     m_nVal;
    
    private String  m_sScreenData;  // This variable holds the incremental update to the screen
    private String  m_sIOBuffer;    // This variable holds the current data entered on the command prompt
    
    public static int IO_FETCH;
    public static int IO_FETCH_STR;
    public static int IO_FETCH_INT;
    public static int IO_STORE;
    public static int IO_STORE_STR;
    public static int IO_STORE_INT;
    
}
